use std::str;

use crate::gen_title;

pub fn ch2_8_1() {
    gen_title("ch2_8_1", 18);

    #[allow(unused_variables)]
    type File = String;

    fn open(f: &mut File) -> bool {
        true
    }

    fn close(f: &mut File) -> bool {
        true
    }

    #[allow(dead_code)]
    fn read(f: &mut File, save_to: &mut Vec<u8>) -> ! {
        unimplemented!()
    }

    let mut f1 = File::from("f1.txt");
    open(&mut f1);
    close(&mut f1);
}

pub fn ch2_8_2() {
    gen_title("ch2_8_2", 18);

    let my_name = "Pascal".to_string();
    greet(my_name);

    fn greet(name: String) {
        println!("Hello, {}!", name);
    }
}

pub fn ch2_8_3() {
    gen_title("ch2_8_3", 18);

    let s = String::from("hello world");

    let hello = &s[0..5];
    let world = &s[6..11];

    println!("{}, {}", hello, world);

    let s = String::from("hello");
    let slice = &s[0..2];
    println!("{}", slice);
    let slice = &s[..2];
    println!("{}", slice);

    let s = String::from("hello");
    let len = s.len();
    let slice = &s[4..len];
    println!("{}", slice);
    let slice = &s[4..];
    println!("{}", slice);

    let s = String::from("hello");
    let len = s.len();
    let slice = &s[0..len];
    println!("{}", slice);
    let slice = &s[..];
    println!("{}", slice);
}

pub fn ch2_8_4() {
    gen_title("ch2_8_4", 18);

    let mut s = String::from("hello world");
    let word = first_word(&s);
    // s.clear();
    println!("the first word is: {}", word);

    fn first_word(s: &String) -> &str {
        &s[..1]
    }
}

pub fn ch2_8_5() {
    gen_title("ch2_8_5", 18);

    let a = [1, 2, 3, 4, 5];

    let slice = &a[1..3];

    println!("{:?}", slice);
}

pub fn ch2_8_6() {
    gen_title("ch2_8_6", 18);
    let s = String::from("hello, world");

    say_hello(&s);
    say_hello(&s[..]);
    say_hello(s.as_str());

    fn say_hello(s: &str) {
        println!("{}", s);
    }
}

pub fn ch2_8_7() {
    gen_title("ch2_8_7", 18);

    let mut s = String::from("hello ");
    s.push_str("rust");
    println!("{}", s);

    s.push('!');
    println!("{}", s);
}

pub fn ch2_8_8() {
    gen_title("ch2_8_8", 18);
    let mut s = String::from("hello rust!");
    s.insert(5, ',');
    println!("{}", s);
    s.insert_str(6, " I like");
    println!("{}", s);
}

pub fn ch2_8_9() {
    gen_title("ch2_8_9", 18);
    let string_replace = String::from("I like rust. Learning rust is my favorite!");
    let new_string_replace = string_replace.replace("rust", "RUST");
    print!("{}", new_string_replace);
}

pub fn ch2_8_10() {
    gen_title("ch2_8_10", 18);
    let mut string_replace_range = String::from("I like rust!");
    string_replace_range.replace_range(7..8, "R");
    println!("{}", string_replace_range);
}

pub fn ch2_8_11() {
    gen_title("ch2_8_11", 18);
    let mut string_pop = String::from("rust pop 中文!");
    let p1 = string_pop.pop();
    let p2 = string_pop.pop();
    dbg!(p1);
    dbg!(p2);
    dbg!(string_pop);
}

pub fn ch2_8_12() {
    gen_title("ch2_8_12", 18);
    let mut string_remove = String::from("测试remove方法");
    println!(
        "string_remove占{}个字节",
        std::mem::size_of_val(string_remove.as_str())
    );
    string_remove.remove(0);
    dbg!(string_remove);
}

pub fn ch2_8_13() {
    gen_title("ch2_8_13", 18);
    let mut string_truncate = String::from("测试truncate");
    string_truncate.truncate(3);
    dbg!(string_truncate);
}

pub fn ch2_8_14() {
    gen_title("ch2_8_14", 18);
    let mut string_clear = String::from("string clear");
    string_clear.clear();
    dbg!(string_clear);
}

pub fn ch2_8_15() {
    gen_title("ch2_8_15", 18);

    let string_append = String::from("hello ");
    let string_rust = String::from("rust");
    let result = string_append + &string_rust;
    let mut result = result + "!";
    result += "!!!";

    println!("{}", result);
}

pub fn ch2_8_16() {
    gen_title("ch2_8_16", 18);
    let s1 = String::from("tic");
    let s2 = String::from("tac");
    let s3 = String::from("toe");

    let s = s1 + "-" + &s2 + "-" + &s3;
    println!("{}", s);
}

pub fn ch2_8_17() {
    gen_title("ch2_8_17", 18);
    let s1 = "hello";
    let s2 = String::from("rust");
    let s = format!("{} {}!", s1, s2);
    println!("{}", s);
}

pub fn ch2_8_18() {
    gen_title("ch2_8_18", 18);
    let byte_escape = "I'm writing \x52\x75\x73\x74!";
    println!("What are you doing\x3F (\\x3F means ?) {}", byte_escape);

    let unicode_codepoint = "\u{211D}";
    let character_name = "\"DOUBLE-STRUCK CAPITAL R\"";
    println!(
        "Unicode character {} (U+211D) is called {}",
        unicode_codepoint, character_name
    );

    let long_string = "String literals
    can span multiple lines.
    The linebreak and indentation here ->\
    <- can be escaped too!";

    println!("{}", long_string);
}

pub fn ch2_8_19() {
    gen_title("ch2_8_19", 18);

    println!("{}", "hello \\x52\\x75\\x73\\x74");
    let raw_str = r"Escapes don't work here: \x3F \u{211D}";
    println!("{}", raw_str);

    let quotes = r#"And then I saild: "There is no escape!""#;
    println!("{}", quotes);

    let longer_delimiter = r###"A string with "#" in it, And even "##!""###;
    println!("{}", longer_delimiter);
}

pub fn ch2_8_20() {
    gen_title("ch2_8_20", 18);

    for c in "中国人".chars() {
        println!("{}", c);
    }

    for b in "中国人".bytes() {
        println!("{}", b);
    }
}

pub fn ch2_8_pra_1() {
    gen_title("ch2_8_pra_1", 18);

    let s: &str = "hello,world";

    println!("{}", s);
}

pub fn ch2_8_pra_2() {
    gen_title("ch2_8_pra_2", 18);

    let s: Box<str> = "hello, world".into();
    greetings(s);

    fn greetings(s: Box<str>) {
        println!("{}", s);
    }
}

pub fn ch2_8_pra_3() {
    gen_title("ch2_8_pra_3", 18);

    let mut s = "".to_string();
    s.push_str("hello, world");
    s.push('!');

    assert_eq!(s, "hello, world!");
    println!("{}", s);
}

pub fn ch2_8_pra_4() {
    gen_title("ch2_8_pra_4", 18);

    let mut s = String::from("hello");
    s.push(',');
    s.push_str(" world");
    s += &"!".to_string();

    println!("{}", s);
}

pub fn ch2_8_pra_5() {
    gen_title("ch2_8_pra_5", 18);

    let s = String::from("I like dogs");
    let s1 = s.replace("dogs", "cats");

    assert_eq!(s1, "I like cats");
    println!("{}", s1);
}

pub fn ch2_8_pra_6() {
    gen_title("ch2_8_pra_6", 18);

    let s1 = String::from("hello, ");
    let s2 = String::from("world!");
    let s3 = s1 + &s2;
    assert_eq!(s3, "hello, world!");
    println!("{}", s3);
}

pub fn ch2_8_pra_7() {
    gen_title("ch2_8_pra_7", 18);

    let s = "hello, world".to_string();
    greetings(s);
    fn greetings(s: String) {
        println!("{}", s);
    }
}

pub fn ch2_8_pra_8() {
    gen_title("ch2_8_pra_8", 18);

    let s = "hello, world!".to_string();
    let s1: &str = &s;
    println!("{} {}", s, s1);
}

pub fn ch2_8_pra_9() {
    gen_title("ch2_8_pra_9", 18);

    let byte_string: &[u8; 21] = b"this is a byte string";

    println!("A byte string: {:?}", byte_string);

    let escaped = b"\x52\x75\x73\x74 as bytes";
    println!("Some escaped bytes: {:?}", escaped);

    let raw_byte_string = br"\u{211D} is not escaped here";
    println!("{:?}", raw_byte_string);

    if let Ok(my_str) = str::from_utf8(raw_byte_string) {
        println!("And the same as text: {}", my_str);
    }

    let _quotes = br#"You can also use "fancier" fromatting, \
    like with normal raw strings"#;
    let shift_jis = b"\x82\xe6\x82\xa8\xb1\x82\xbb";

    match str::from_utf8(shift_jis) {
        Ok(my_str) => println!("Conversion successful: '{}'", my_str),
        Err(e) => println!("Conversion failed: {:?}", e),
    };
}

pub fn ch2_8_pra_10() {
    gen_title("ch2_8_pra_10", 18);

    let s1 = String::from("hi, 中国");
    let h = &s1[0..1];
    assert_eq!(h, "h");
    println!("{}", h);

    let h1 = &s1[4..7];
    assert_eq!(h1, "中");
    println!("{}", h1);
}

pub fn ch2_8_pra_11() {
    gen_title("ch2_8_pra_11", 18);
    for c in "你好, 世界".chars() {
        println!("{}", c);
    }
}

pub fn ch2_8_pra_12() {
    gen_title("ch2_8_pra_12", 18);

    let s = "The 🚀 goes to the 🌑!";

    let rocket = utf8_slice::slice(s, 4, 5);
    println!("{}", rocket);
}
